import qs from 'qs';
import router from '@/router';
import Cookies from 'js-cookie';
import config from '../config/index';
import { clearLogin } from '@/utils';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import isPlainObject from 'lodash/isPlainObject';

export type ResType<T> = {
  code: number;
  data?: T;
  msg: string;
  err?: string;
};

class RequestHttp {
  server: AxiosInstance;
  public constructor() {
    this.server = axios.create({
      // 默认地址请求地址，可在config文件中修改
      baseURL: config,
      // 设置超时时间
      timeout: 8000,
    });
    /**
     * @description 请求拦截器
     * token校验(JWT) : 接受服务器返回的 token,存储到 vuex/pinia/本地储存当中
     */
    this.server.interceptors.request.use(
      (config) => {
        config!.headers!['Accept-Language'] = Cookies.get('language') || 'zh-CN';
        config!.headers!['token'] = Cookies.get('token') ?? '';
        if (config.method === 'get') {
          config.params = {
            ...config.params,
            ...{ _t: new Date().getTime() },
          };
        }
        if (isPlainObject(config.params)) {
          config.params = {
            ...config.params,
          };
        }
        if (isPlainObject(config.data)) {
          config.data = {
            ...config.data,
          };
          if (/^application\/x-www-form-urlencoded/.test(config!.headers!['content-type'] as string)) {
            config.data = qs.stringify(config.data);
          }
        }
        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
    /**
     * @description 响应拦截器
     */
    this.server.interceptors.response.use(
      (response) => {
        const { data, config } = response;
        if (data.code === 401 || data.code === 10001) {
          clearLogin();
          router.replace({ name: 'login' });
          return Promise.reject(data.msg);
        }
        return data;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
  }
  /**
   * @description 常用请求方法封装
   */
  get<T>(url: string, params?: object): Promise<ResType<T>> {
    return this.server.get(url, { params });
  }
  post<T>(url: string, params?: object | string, headers = { 'Content-Type': 'application/json;charset=UTF-8' }): Promise<ResType<T>> {
    return this.server.post(url, params, { headers });
  }
  put<T>(url: string, params: object, headers = { 'Content-Type': 'application/json;charset=UTF-8' }): Promise<ResType<T>> {
    return this.server.put(url, params, { headers });
  }
  delete<T>(url: string, params: any): Promise<ResType<T>> {
    return this.server.delete(url, params);
  }
  upload(url: string, file: any, headers = { 'Content-Type': 'multipart/form-data' }): Promise<BlobPart> {
    return this.server.post(url, file, { headers });
  }
  download(url: string, params?: object, headers = { 'Content-Type': 'multipart/form-data' }): Promise<BlobPart> {
    return this.server.post(url, params, { headers });
  }
}
export default new RequestHttp();
